package gbench.appdemo.myworld.junit;

import static gbench.appdemo.myworld.market.commodity.Commodity.COMMODITY;
import static gbench.common.tree.LittleTree.IRecord.REC;
import static gbench.common.tree.LittleTree.Tuple2.TUP2;

import java.text.MessageFormat;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.junit.jupiter.api.Test;

import gbench.appdemo.myworld.economy.Economy;
import gbench.appdemo.myworld.economy.demand.Demand;
import gbench.appdemo.myworld.economy.society.Society;
import gbench.appdemo.myworld.market.SimpleMarket;
import gbench.appdemo.myworld.market.commodity.Commodity;
import gbench.appdemo.myworld.util.Latch;
import gbench.common.tree.LittleTree.Tuple2;

public class JunitSociety {
    
    final Commodity grain = COMMODITY("粮食", "公斤");
    final Commodity wheal = COMMODITY("小麦", "公斤");
    final Commodity rmb = COMMODITY("RMB", "元");
    final Commodity labor = COMMODITY("产业劳动", "天");
    final Commodity bread = COMMODITY("面包", "个");
    
    /**
     * 获得商品列表
     * 
     * @return
     */
    public List<Commodity> commodities() {
        return Arrays.stream(this.getClass().getDeclaredFields())
        .filter(e -> Commodity.class.isAssignableFrom(e.getType())).map(e -> {
            try {
                final var value = (Commodity) e.get(this);
                return value;
            } catch (Exception e1) {
                e1.printStackTrace();
            } // try
            return null;
        }).filter(e -> e != null).collect(Collectors.toList());
    }
    
    @SuppressWarnings("unchecked")
    @Test
    public void foo() {
        final var society = new Society("商品经纪社会",1000);
        society.initialize(2,10);// 构造一个千人社会
        final var cc = commodities().toArray(Commodity[]::new);
        final var n = cc.length;
        final List<Tuple2<String,Commodity>> tups = Stream.iterate(0, i->i+1).limit(100)
            .map(i->TUP2(i+"",cc[i%n]))
            .collect(Collectors.toList());
        final var market = SimpleMarket.of("商品市场",rmb);
        final var broker = market.getTradeBroker(tups.toArray(o->new Tuple2[o]));// 制作一个交易代理。
        society.restart(market, (commdities,demand)->{
            commdities.parallel().findAny().ifPresent(commodity->{
                System.out.println(commodity);
                demand.resolve();
                System.out.println("\n 匹配到了:"+demand);
                broker.purchase(commodity, 1, 1000);
            });
        });
    }
    
    @Test
    public void bar() throws InterruptedException {
        final var produce_latch = new Latch(1);// 生产活动控制锁
        final var program = new Latch(1); // 程序终止活动控制锁
        
        // 社会生产
        final var society = new Society("商品经纪社会",1000).initialize(2,10);// 构造一个千人社会
        final var cc = commodities().toArray(Commodity[]::new); // 社会产品集合：构造现实生活
        final List<Tuple2<String,Commodity>> tups = Stream.iterate(0, i->i+1).limit(100)
            .map(i->TUP2("张"+i,cc[i%cc.length])).collect(Collectors.toList()); // 构造商品经营许可 申请
        final var market = SimpleMarket.of("商品市场",rmb); // 创建一个商品消费市场
        final var broker = market.getTradeBroker(tups);// 构造 商品经纪
        
        // 经济生产
        new Economy((int) Math.pow(2, 4)) // 构造一个经济体
        .produce(economy -> {// 工业生产
            // 启动一个社会
            society.restart(market, (commdities,demand)->{
                commdities.findAny().ifPresent(commodity->{
                    final var rec = REC("demand", demand,"commodity",commodity);
                    economy.publish(rec);
                });
            });
            produce_latch.countdown();
        }).consume(event -> {// 社会生活
            // 商品交易经纪
            final var commodity = event.get("commodity",Commodity.class); // 提取目标商品
            final var demand = event.get("demand",Demand.class); // 提取 用户需求
            broker.purchase(commodity, demand.getQuantity(), 1000);
            demand.resolve();
            System.out.println(MessageFormat.format("demand:{0} 匹配  commodity:{1}", demand,commodity));
        }).collect(e -> {
            produce_latch.await();
            System.out.println("shutdown");
            e.shutdown();
            program.countdown();
        });// collect
        
        program.await();
        System.out.println("经济体结束");
    }

}
